package com.hm.health.Utils;

import android.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;


public class FileLogUtil {
    private static final String TAG = "FileLogUtil";
    private static final int DATA_BUFFER_SIZE_MAX = 1024 * 500;
    private StringBuffer mDataBuffer = new StringBuffer();
    private LinkedBlockingQueue<String> mSaveDataQueue;
    private AtomicBoolean mIsStartSaveData = new AtomicBoolean(false);
    private SimpleDateFormat spdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
    private String mFilePath;
    private String mFileName;
    private String mFullPath;
    private DataSaveThread mDataSaveThread;
    private AtomicBoolean mSaveWithBuffer = new AtomicBoolean(true);

    /**
     * FileLog Util constructor
     * @param dir   relative path
     * @param fileName   file name
     */
    public FileLogUtil(String dir, String fileName) {
        dir.replace('\\', '/');
        if(!(dir.lastIndexOf('/') == (dir.length() - 1))) {
            dir += '/';
        }
        this.mFilePath = dir;
        this.mFileName = fileName;
        mSaveDataQueue = new LinkedBlockingQueue<>();
        mSaveWithBuffer.set(true);
    }

    public String getFilePath() {
        return mFilePath;
    }

    public void setSaveWithBuffer(boolean realtimeSave) {
        mSaveWithBuffer.set(realtimeSave);
    }

    /**
     * Start save log to file
     */
    public void startSave() {
        generatorFilePath();
        mDataBuffer.delete(0, mDataBuffer.length());
        mSaveDataQueue.clear();
        mIsStartSaveData.set(true);
        if (null == mDataSaveThread) {
            mDataSaveThread = new DataSaveThread();
        }
        mDataSaveThread.start();
    }

    /**
     * Generator file path
     * @return
     */
    private void generatorFilePath() {
        String fileBasePath = mFilePath;
        File dir = new File(fileBasePath);
        if (!dir.exists()) {
            if (dir.mkdirs()) {
                Log.i(TAG, "success create dir");
            } else {
                Log.e(TAG,"failed create dir");
            }
        }

        mFullPath = fileBasePath + mFileName;
        Log.i(TAG, fileBasePath + "is created");
    }

    /**
     * Finish save data
     */
    public void finishedSave() {
        mIsStartSaveData.set(false);
        if (null != mDataSaveThread) {
            mDataSaveThread.interrupt();
            mDataSaveThread = null;
        }
    }

    /**
     * save string to buffer
     * @param buffer
     */
    public void saveData(String buffer) {
        if(mIsStartSaveData.get()) {
            mSaveDataQueue.add(buffer);
        }
    }

    public class DataSaveThread extends Thread {

        @Override
        public void run() {
            while (true) {
                try {
                    String line = mSaveDataQueue.take();
                    if (null != line && !line.isEmpty()) {
                        mDataBuffer.append(line);
                    }

                    if ((mDataBuffer.length() > DATA_BUFFER_SIZE_MAX) && mSaveWithBuffer.get()) {
                        restoreLogInfo2File(mFullPath, mDataBuffer);
                        mDataBuffer.delete(0, mDataBuffer.length());
                    } else {
                        restoreLogInfo2File(mFullPath, mDataBuffer);
                        mDataBuffer.delete(0, mDataBuffer.length());
                    }

                } catch (InterruptedException e) {
                    Log.d(TAG, "DataSaveThread: mSaveDataQueue size --> " + mSaveDataQueue.size());
                    Log.d(TAG, "InterruptedException: mDataBuffer size --> " + mDataBuffer.length());
                    Iterator<String> iterator = mSaveDataQueue.iterator();
                    while (iterator.hasNext()) {
                        mDataBuffer.append(iterator.next());
                    }
                    restoreLogInfo2File(mFullPath, mDataBuffer);
                    mDataBuffer.delete(0, mDataBuffer.length());
                    mSaveDataQueue.clear();
                    Log.d(TAG, "Finished save buffer");
                }
            }
        }
    }

    public boolean restoreLogInfo2File(String path, StringBuffer data) {
        boolean result = false;
        Log.i(TAG, "restoreFingerData2File enter,path:" + path);
        do {

            if (null == path) {
                break;
            }

            if (path.isEmpty()) {
                Log.e(TAG, "path can not be null");
                break;
            }

            if (data == null) {
                Log.e(TAG, "data can not be null");
                break;
            }
            RandomAccessFile file = null;
            try {
                file = new RandomAccessFile(path, "rw");
                file.seek(file.length());
                file.write(data.toString().getBytes());
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (file != null) {
                    try {
                        file.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            result = true;
        } while (false);

        Log.i(TAG, "restoreLogInfo2File result:" + result);
        return result;
    }


}
